// Copyright 2011 Bryan McKelvey

/**
 * @fileoverview Main background script.
 * @author bryan.mckelvey@gmail.com (McKelvey Bryan)
 */

/**
 * Background script functions.
 * @namespace Background script functions.
 */
var Background = (function() {
 
  /**
   * List of main sources for links. Used to determine which picture to show on ESPN scoreboard.
   * @type {Array.<RegExp,string>}
   * @final
   */
  var SCHOOL_NAME_STANDARDIZATIONS = [
    {search: /n(?:orth)?(?:ern)?\.?\s/,   replacement: 'n '},
    {search: /s(?:outh)?(?:ern)?\.?\s/,   replacement: 's '},
    {search: /east(?:ern)?\s/,            replacement: 'e '},
    {search: /west(?:ern)?\s/,            replacement: 'w '},
    {search: 'state',                     replacement: 'st'},
    {search: 'saint ',                    replacement: 'st '},
    {search: 'university',                replacement: 'u'},
    {search: 'brigham young',             replacement: 'byu'},
    {search: /^connecticut$/,             replacement: 'uconn'},
    {search: 'georgia',                   replacement: 'ga'},
    {search: 'mississippi',               replacement: 'miss'},
    {search: 'marymount',                 replacement: 'mary'},
    {search: 'n carolina',                replacement: 'nc'},
    {search: 's carolina',                replacement: 'sc'},
    {search: 'texas',                     replacement: 'tx'},
    {search: 'virginia',                  replacement: 'va'},
    {search: 'illinois-chicago',          replacement: 'uic'},
    {search: /\-/g,                       replacement: ' '},
    {search: /\./g,                       replacement: ''},
    {search: /^\s+|\s+$/g,                replacement: ''}
  ];

  /**
   * List of main sources for links. Used to determine which picture to show on ESPN scoreboard.
   * @type {Object.<string>}
   * @final
   */
  var STREAM_SOURCES = {
    'ESPN3': 'espn.go.com',
    'StreamTorrent': 'st://',
    'TVU': 'tvu://',
    'CBS Sports': 'cbssports.com',
    'Directon.tv': 'directon.tv',
    'Justin.tv': 'justin.tv',
    'ohlulz': 'ohlulz.com',
    'Veetle': 'veetle.com',
    'B2TV': 'b2tv.com',
    'RTMP': 'rtmp://'
  };

  /**
   * Default settings for local storage.
   * @type {Object.<boolean>}
   * @final
   */
  var DEFAULT_SETTINGS = {
    'showEspn3': true
  };

  /**
   * The base URL for the Myp2p forums.
   * @type {string}
   * @final
   */
  var MYP2P_FORUM_BASE_URL = 'http://www.myp2pforum.eu/';
   
  /**
   * The URL for which we look up the appropriate NCAA thread.
   * @type {string}
   * @final
   */
  var MYP2P_FORUM_NCAA_URL = 'forums/33-NCAA';

  /**
   * Determines whether a thread contains NCAA basketball info and extracts the date range into backrefs 1-4.
   * @type {RegExp}
   * @final
   */
  var BASKETBALL_REGEX = /ncaa\-basketball\-([a-z]{3,4})\-([12][0-9]|3[0-1]|[1-9])\-([a-z]{3,4})\-([12][0-9]|3[0-1]|[1-9])/i;

  /**
   * Determines whether a text node contains game stream information.
   * @type {RegExp}
   * @final
   */
  var GAME_REGEX = /\s+(?:0[1-9]|1[0-2])\:[0-5][0-9]\s[ap]m\s\|/i;

  /**
   * Determines the names of the teams playing in a game.
   * @type {RegExp}
   * @final
   */
  var TEAMS_REGEX = /\|\s(?:\#(?:1[0-9]|2[0-5]|[1-9])\s)?(.*?)\s(?:vs\.|\@|at)\s(?:\#(?:1[0-9]|2[0-5]|[1-9])\s)?(.*?)(?:\s\||$)/i;

  /**
   * Included for backwards compatibility with IE, which doesn't understand Node.TEXT_NODE.
   * @type {number}
   * @final
   */
  var TEXT_NODE_TYPE = 3;

  /**
   * Maximum number of nodes forward to search for links
   * @type {number}
   * @final
   */
  var MAX_LINK_ITER = 10;

  /**
   * Denotes the first match in a regular expression.
   * @type {number}
   * @final
   */
  var FIRST_MATCH = 1;

  /**
   * List of games discovered.
   * @type {Object}
   */
  var gameList = {};

  /**
   * Script is done looking through threads.
   * @type {boolean}
   */
  var threadSearchDone = false;

  /**
   * Script is done looking through games in threads it's found.
   * @type {boolean}
   */
  var gameSearchDone = false;

  /**
   * Total number of threads found.
   * @type {number}
   */
  var threadsFound = 0;

  /**
   * Total number of threads searched through.
   * @type {number}
   */
  var threadsSearched = 0;

  /**
   * Gets the type of stream so an icon can be chosen for display on ESPN's scoreboard
   * @param {string} url The stream's url.
   * @return {string} The type of stream.
   */
  function getStreamType(url) {
    var temp = 'Other';
    $.each(STREAM_SOURCES, function(type, search) {
      // If a match is found, set temp to that type and break the loop
      if (url.indexOf(search) > -1) {
        temp = type;
        return false;
      }
    });
    return temp;
  }

  /**
   * Standardizes the names of schools due to different spelling conventions for 'North/South/East/West,' 'State,' etc.
   * @param {string} school The unstandardized name of the school.
   * @return {string} The standardized name of the school.
   */
  function standardizeSchoolName(school) {
    school = school.toLowerCase();
    $.each(SCHOOL_NAME_STANDARDIZATIONS, function(index, standardization) {
      school = school.replace(standardization.search, standardization.replacement);
    });
    return school;
  }

  /**
   * Loads NCAA basketball-relevant threads and parses their content for games.
   * @param {string} url The path to the thread, excluding the domain name defined in MYP2P_FORUM_BASE_URL.
   */
  function searchForGames(url) {
    $.ajax({
      url: MYP2P_FORUM_BASE_URL + url,
      success: function(data) {
        $('blockquote.postcontent:not(:contains("Women"))', data).contents().filter(function() { return this.nodeType == TEXT_NODE_TYPE; }).each(function() {
          if (GAME_REGEX.test($(this).text())) {
            var teams = TEAMS_REGEX.exec($(this).text());
            
            if (teams) {
              var a = standardizeSchoolName(teams[1]);
              var b = standardizeSchoolName(teams[2]);

              // Set team that comes first alphabetically as first team
              var firstTeam;
              var secondTeam;

              if (a < b) {
                firstTeam = a;
                secondTeam = b;
              } else {
                firstTeam = b;
                secondTeam = a;
              }

              var links = [];
              var i = 0;
              var node = this.nextSibling;
              while (node && !TEAMS_REGEX.test($(node).text()) && i++ < MAX_LINK_ITER) {
                var href = $(node).attr('href');
                if (href) {
                  links.push({type: getStreamType(href), url: href});
                }
                node = node.nextSibling;
              }
              if (!gameList[firstTeam]) {
                gameList[firstTeam] = {};
              }
              gameList[firstTeam][secondTeam] = links;
            }
          }
        });
        threadsSearched++;
        if (threadsSearched === threadsFound) {
          gameSearchDone = true;
        }
        console.log(gameList);
      }
    });
  }

  /**
   * Loads the basketball forum URL and looks for threads that contain NCAA basketball stream information.
   */
  function searchForThread() {
    $.ajax({
      url: MYP2P_FORUM_BASE_URL + MYP2P_FORUM_NCAA_URL,
      success: function(data) {
        $('li.threadbit a.title', data).each(function() {
          var url = $(this).attr('href');
          var dates = BASKETBALL_REGEX.exec(url);
          if (dates) {
            threadsFound++;
            searchForGames(url);
          }
        });
        threadSearchDone = true;
      },
      error: function() {
        // error handler
      }
    });
  }

  /**
   * Listens for requests from content scripts.
   * @param {Object.<string>} request Request sent from the content script.
   * @param {Object} sender blah.
   * @sendResponse {Object.<string>} sender Return values to the content script.
   * @return {string} Some return value.
   */
  chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    switch (request.type) {
      case 'done':
        sendResponse({done: gameSearchDone});
        break;
      case 'games':
        var a = standardizeSchoolName(request.teams[0]);
        var b = standardizeSchoolName(request.teams[1]);
        var links = [];
        
        // Set team that comes first alphabetically as first team
        var firstTeam;
        var secondTeam;

        if (a < b) {
          firstTeam = a;
          secondTeam = b;
        } else {
          firstTeam = b;
          secondTeam = a;
        }

        if (gameList[firstTeam]) {
          if (gameList[firstTeam][secondTeam]) {
            sendResponse({links: gameList[firstTeam][secondTeam]});
          } else {
            sendResponse({links: []});
          }
        } else {
          sendResponse({links: []});
        }
        break;
      case 'settings':
        var temp = {};

        // Get settings from local storage
        for (var key in localStorage) {
          temp[key] = JSON.parse(localStorage[key]);
        }

        sendResponse({settings: temp});
        break;
      default:
        sendResponse({});
        break;
    }
  });

  // Listen for any changes to the URL of any tab.
  chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (tab.url.indexOf('scores.espn.go.com') > -1) {
      chrome.pageAction.show(tabId);
    }
  });

  /**
   * Retrieves settings and, if necessary, restores defaults.
   */
  function getSettings() {
    // Set any blank settings to their defaults
    $.each(DEFAULT_SETTINGS, function(key, value) {
      if (!localStorage[key]) {
        localStorage[key] = JSON.stringify(value);
      }
    });
  }

  searchForThread();
  getSettings();
}());